#pragma once

using namespace System;
using namespace System::Text;
using namespace System::Runtime::InteropServices;

namespace SbCli
{
	public ref class SafeConv sealed
	{
	private:
		SafeConv()
		{
		}

	public:
		//
		static short ToShort(bool value)
		{
			return (short)(value ? 1 : 0);
		}

		//
		static int ToInt(bool value)
		{
			return value ? 1 : 0;
		}

		//
		static long long ToLong(bool value)
		{
			return value ? 1 : 0;
		}

		//
		static float ToSingle(String^ value)
		{
			try
			{
				return Convert::ToSingle(value);
			}
			catch (...)
			{
				try
				{
					return Convert::ToSingle(value->Trim());
				}
				catch (...)
				{
					return 0.0f;
				}
			}
		}

		//
		static double ToDouble(String^ value)
		{
			try
			{
				return Convert::ToDouble(value);
			}
			catch (...)
			{
				try
				{
					return Convert::ToDouble(value->Trim());
				}
				catch (...)
				{
					return 0;
				}
			}
		}

		//
		static Byte ToByte(String^ value)
		{
			try
			{
				return Convert::ToByte(value);
			}
			catch (...)
			{
				try
				{
					return Convert::ToByte(value->Trim());
				}
				catch (...)
				{
					return 0;
				}
			}
		}

		//
		static short ToShort(String^ value)
		{
			try
			{
				return Convert::ToInt16(value);
			}
			catch (...)
			{
				try
				{
					return Convert::ToInt16(value->Trim());
				}
				catch (...)
				{
					return 0;
				}
			}
		}

		//
		static int ToInt(String^ value)
		{
			try
			{
				return Convert::ToInt32(value);
			}
			catch (...)
			{
				try
				{
					return Convert::ToInt32(value->Trim());
				}
				catch (...)
				{
					return 0;
				}
			}
		}

		//
		static long long ToLong(String^ value)
		{
			try
			{
				return Convert::ToInt64(value);
			}
			catch (...)
			{
				try
				{
					return Convert::ToInt64(value->Trim());
				}
				catch (...)
				{
					return 0;
				}
			}
		}

		//
		static String^ ToStringUTF8(IntPtr pNativeData)
		{
			Byte* walk = (Byte*)pNativeData.ToPointer();
			while (*walk != 0) walk++;
			int length = (int)(walk - (Byte*)pNativeData.ToPointer());

			array<Byte>^ strbuf = gcnew array<Byte>(length);
			Marshal::Copy((IntPtr)pNativeData, strbuf, 0, length);
			String^ data = Encoding::UTF8->GetString(strbuf);

			return data;
		}

		//
		static short ToShort(String^ value, int numbase)
		{
			try
			{
				return Convert::ToInt16(value, numbase);
			}
			catch (...)
			{
				return 0;
			}
		}

		//
		static int ToInt(String^ value, int numbase)
		{
			try
			{
				return Convert::ToInt32(value, numbase);
			}
			catch (...)
			{
				return 0;
			}
		}

		//
		static long long ToLong(String^ value, int numbase)
		{
			try
			{
				return Convert::ToInt64(value, numbase);
			}
			catch (...)
			{
				return 0;
			}
		}

		//
		static String^ ToString(int value, int numbase)
		{
			try
			{
				return Convert::ToString(value, numbase);
			}
			catch (...)
			{
				return String::Empty;
			}
		}

		//
		static String^ ToString(long long value, int numbase)
		{
			try
			{
				return Convert::ToString(value, numbase);
			}
			catch (...)
			{
				return String::Empty;
			}
		}

		//
		static float ToSingle(array<String^>^ arr, int index)
		{
			return (index < arr->GetLength(0)) ? ToSingle(arr[index]) : 0.0f;
		}

		//
		static short ToShort(array<String^>^ arr, int index)
		{
			return (short)((index < arr->GetLength(0)) ? ToShort(arr[index]) : 0);
		}

		//
		static int ToInt(array<String^>^ arr, int index)
		{
			return (index < arr->GetLength(0)) ? ToInt(arr[index]) : 0;
		}

		//
		static long long ToLong(array<String^>^ arr, int index)
		{
			return (index < arr->GetLength(0)) ? ToLong(arr[index]) : 0;
		}

		//
		static short ToShort(array<Byte>^ arr)
		{
			int len = arr->Length;
			if (len == 0)
				return 0;
			if (len == 1)
				return arr[0];
			return (short)(arr[0] | (arr[1] << 8));
		}

		//
		static array<String^>^ Split(String^ value, array<wchar_t>^ div)
		{
			return value->Split(div);
		}

		//
		static array<String^>^ Split(String^ value, wchar_t div)
		{
			return value->Split(div);
		}

		//
		static String^ RemoveSpace(String^ value)
		{
			if (value == String::Empty)
				return String::Empty;

			array<wchar_t>^ div = gcnew array < wchar_t > { L' ', L'\n', L'\r', L'\t' };
			array<String^>^ arr = value->Split(div);

			return String::Concat(arr);
		}

		//
		static String^ RemoveChar(String^ value, wchar_t rm)
		{
			if (value == String::Empty)
				return String::Empty;

			array<String^>^ arr = value->Split(rm);

			return String::Concat(arr);
		}

		//
		static String^ RemoveChar(String^ value, array<wchar_t>^ rm)
		{
			if (value == String::Empty)
				return String::Empty;

			array<String^>^ arr = value->Split(rm);

			return String::Concat(arr);
		}

		//
		static int SplitPath(String^ path, [Out] String^% dir, [Out] String^% filename)
		{
			if (path == String::Empty)
			{
				dir = String::Empty;
				filename = String::Empty;
				return 0;
			}

			int slash = -1;
			int len = path->Length;
			int i;

			for (i = 0; i < len; ++i)
			{
				if (path[i] == L'/' || path[i] == L'\\')
					slash = i;
			}

			if (slash < 0)
			{
				dir = String::Empty;
				filename = path;
				return 1;
			}
			else
			{
				dir = path->Substring(0, slash);
				filename = path->Substring(slash + 1);
				return 2;
			}
		}

		//
		static bool IsRealNumber(String^ str)
		{
			bool isok = true;
			ASCIIEncoding^ ae = gcnew ASCIIEncoding();
			array<wchar_t>^ tchs = str->Trim()->ToCharArray();

			for (int i = 0; i < tchs->Length; i++)
			{
				array<Byte>^ bc = ae->GetBytes(tchs[i].ToString());

				// '0' ~ '9'
				if (bc[0] >= 0x30 && bc[0] <= 0x39)
					continue;

				// '+'
				if (bc[0] == 0x2b)
					continue;

				// '-'
				if (bc[0] == 0x2d)
					continue;

				// '.'
				if (bc[0] == 0x2e)
					continue;

				// error
				isok = false;
				break;
			}

			return isok;
		}
	};
}
